package com.zhou;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONReader;
import org.jsoup.Connection;
import org.jsoup.Jsoup;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class App {

    private Config config = new Config();

    public static void main(String[] args) {
        new App().run(args);
    }

    /**
     * 入口程序
     *
     * @param args
     */
    public void run(String[] args) {
        if (args.length >= 4) {
            config.setParamStrs(args[0]);
            config.setStartDate(args[1]);
            config.setEndDate(args[2]);
            config.setPageSize(Integer.parseInt(args[3]));
        }

        System.out.println("\n\n================配置信息=================");
        String searchConfig = config.getSearchConfig();
        System.out.println(searchConfig);
        System.out.println("=========================================\n");

        if (new File("data.accdb").exists() == false) {
            System.out.println("data.accdb文件不存在, 请检查后重试!");
            return;
        }

        startDownload();
        System.out.println("完成");
    }

    /**
     * 开始下载
     */
    public void startDownload() {
        Connection.Response response = sendRequest(true);

        if (response == null || response.statusCode() != 200) {
            System.err.println("爬取失败, 状态码为: " + response.statusCode() + ",请重试!");
            return;
        }

        BufferedInputStream bis = response.bodyStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(bis, StandardCharsets.UTF_8));
        JSONReader jsonReader = new JSONReader(br);
        int totalNum = parseTotalNum(jsonReader);
        config.setTotalNum(totalNum);

        System.out.println("请求完成, 开始下载数据...");
        crawlData();
    }

    public void crawlData() {
        for (int i = 0; i < config.getTotalPageNum(); i++) {
            try {
                // 设置页码
                config.setPageNum(i + 1);
                System.out.println(config.getNumConfig());

                Connection.Response response = sendRequest(false);
                if (response == null || response.statusCode() != 200) {
                    System.err.println("爬取失败, 状态码为: " + response.statusCode() + ", 开始重试!");
                    i--;
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                    }
                    continue;
                }

                BufferedInputStream bis = response.bodyStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(bis, StandardCharsets.UTF_8));
                JSONReader jsonReader = new JSONReader(br);
                List<Patent> patents = parseDatas(jsonReader);

                if (i < config.getTotalPageNum() - 1) {
                    if (patents.size() != config.getPageSize()) {
                        i--;
                        System.out.println("下载失败, 重新下载");
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                        }
                        continue;
                    }
                } else if (i == config.getTotalPageNum() - 1) {
                    if (patents.size() != config.getTotalNum() % config.getPageSize()) {
                        i--;
                        System.out.println("下载失败, 重新下载");
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                        }
                        continue;
                    }
                }

                // 存储数据
                MyAccessDataBase.addDatas(patents);
                System.out.println("下载数量：" + patents.size());
            }catch (Exception e){
                i--;
                System.out.println("下载失败, 重新下载");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                }
            }
        }
    }

    /**
     * 发送请求
     *
     * @param isFirst: 是第一次请求吗?
     * @return
     */
    public Connection.Response sendRequest(boolean isFirst) {
        Connection.Response response = null;

        Map<String, String> datas = config.toMap();
        if (isFirst) {
            // 第一次请求设置pageSize = 1为了快速获取总数目
            datas = config.toFirstMap();
        }

        try {
            response = Jsoup.connect(config.getUrl())
                    .data(datas)
                    .method(Connection.Method.POST)
                    .maxBodySize(0)
                    .timeout(config.getTimeout())
                    .execute();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
        return response;
    }

    /**
     * 解析总数目
     *
     * @param jsonReader
     * @return
     */
    public int parseTotalNum(JSONReader jsonReader) {
        // 开始读取json对象
        jsonReader.startObject();
        while (jsonReader.hasNext()) {
            String str = jsonReader.readString();
            if ("pageTotalRows".equals(str)) {
                Integer num = jsonReader.readInteger();
                return num;
            } else {
                jsonReader.readObject();
            }
        }
        return 0;
    }

    /**
     * 解析数据
     */
    public List<Patent> parseDatas(JSONReader jsonReader) {
        List<Patent> patents = new ArrayList<>();
        // 开始读取json对象
        jsonReader.startObject();
        while (jsonReader.hasNext()) {
            String str = jsonReader.readString();
            if ("pageRow".equals(str)) {
                jsonReader.startArray();
                while (jsonReader.hasNext()) {
                    Object o = jsonReader.readObject();
                    Map map = (Map) JSON.parse(o.toString());
                    Patent patent = new Patent(map);
                    patents.add(patent);
                }
                jsonReader.endArray();
            } else {
                jsonReader.readObject();
            }
        }
        return patents;
    }
}
